Jest と Vitest で「関数内で呼び出される関数の戻り値をモックする」方法を比べてみた
こんにちは、CX事業本部 Delivery部の若槻です。
今まで JavaScript テスティングフレームワークとしてずっと Jest を使っていましたが、最近は社内でおすすめされて Vitest を使い始めています。多くのマッチャーや API が Jest と互換性があり、また実行速度が速いのが特徴です。
さて今まで Jest で関数のユニットテストを実装する際に「関数内で呼び出される関数の戻り値をモック」ということをやってきたのですが、これが Vitest ではどうなるのか、方法を比べてみました。
やってみた
関数を実装したモジュールです。
以下は呼び出す側の関数caller
を実装したモジュールmoduleA
です。
import { called } from './moduleB'; export const caller = () => called(2);
以下は呼び出される側の関数called
を実装したモジュールmoduleB
です。
export const called = (max: number) => Math.floor(Math.random() * max);
呼び出す側の関数のユニットテストを Jest と Vitest で実装してみます。
Jest の場合
環境
module.exports = { testEnvironment: 'node', roots: ['<rootDir>/src'], testMatch: ['**/*.test.ts'], transform: { '^.+\\.tsx?$': 'ts-jest', }, };
$ npm ls jest cdk_sample_app@0.1.0 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app ├── jest@29.6.4 └─┬ ts-jest@29.1.1 └── jest@29.6.4 deduped
テストコード
Jest の場合は次のようになります。jest.fn()
でモックしたい関数をモック関数とします。
import { caller } from './moduleA'; import { called } from './moduleB'; test('moduleA', (): void => { (called as jest.Mock) = jest.fn().mockReturnValue(5); const result = caller(); expect(called).toHaveBeenCalledTimes(1); expect(called).toBeCalledWith(2); expect(result).toBe(7); });
テストコードを Jest で実行した様子です。
$ npx jest moduleA-jest.test.ts PASS src/moduleA-jest.test.ts ✓ moduleA (2 ms) Test Suites: 1 passed, 1 total Tests: 1 passed, 1 total Snapshots: 0 total Time: 1.988 s, estimated 2 s Ran all test suites matching /moduleA-jest.test.ts/i.
ちなみにトータルの実行時間は 1.988 s です。
Vitest の場合
環境
$ npm ls vitest cdk_sample_app@0.1.0 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app └── vitest@0.34.3
テストコード
Vitest の場合は次のようになります。まずvi.mock()
でモジュールごとモックし、vi.fn()
でモックしたい関数をモック関数とします。fn()
には下記のmockReturnValue
の他にmockResolvedValue
やmockReturnValueOnce
など Jest と同じものは一通り使えます。
import { caller } from './moduleA'; import { called } from './moduleB'; import { expect, test, vi } from 'vitest'; vi.mock('./moduleB', () => { return { called: vi.fn().mockReturnValue(5), }; }); test('moduleA', (): void => { const result = caller(); expect(called).toHaveBeenCalledTimes(1); expect(called).toBeCalledWith(2); expect(result).toBe(7); });
テストコードを Vitest で実行した様子です。
$ npx vitest run moduleA-vitest.test.ts RUN v0.34.3 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app ✓ src/moduleA-vitest.test.ts (1) ✓ moduleA Test Files 1 passed (1) Tests 1 passed (1) Start at 01:35:07 Duration 252ms (transform 54ms, setup 0ms, collect 48ms, tests 2ms, environment 0ms, prepare 49ms)
トータルの実行時間は 252ms です。Jest と比べて 1/8 くらいの時間です。さすがトップページで「Blazing Fast Unit Test Framework」と謳っているだけあって速いですね。
おわりに
Jest と Vitest で「関数内で呼び出される関数の戻り値をモックする」方法を比べてみました。
マッチャーは基本同じなのですが、このモック部分は異なっていたので少し調査する必要がありました。引き続き Vitest を使って慣れていきたいと思います。
参考
以上